package com.ukefu.webim.web.handler.api.rest;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.ArrayListMultimap;
import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.util.UKTools;
import com.ukefu.util.extra.DataExchangeInterface;
import com.ukefu.util.task.DSData;
import com.ukefu.util.task.DSDataEvent;
import com.ukefu.webim.service.impl.BatchDataProcess;
import com.ukefu.webim.service.impl.ESDataExchangeImpl;
import com.ukefu.webim.service.repository.JobDetailRepository;
import com.ukefu.webim.service.repository.MetadataRepository;
import com.ukefu.webim.service.repository.ReporterRepository;
import com.ukefu.webim.service.repository.SysDicRepository;
import com.ukefu.webim.util.RestResult;
import com.ukefu.webim.util.RestResultType;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.model.Contacts;
import com.ukefu.webim.web.model.JobDetail;
import com.ukefu.webim.web.model.MetadataTable;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.TableProperties;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("/api/batch")
@Api(value = "批次数据导入", description = "批次数据")
public class ApiBatchController extends Handler{
	@Autowired
	private JobDetailRepository batchRes;
	
	@Autowired
	private ESDataExchangeImpl esDataExchange ;
	
	@Autowired
	private ReporterRepository reporterRes ;
	
	@Autowired
	private MetadataRepository metadataRes ;
	/**
	 * 批量提交批次数据
	 * @param request
	 * @param user
	 * @return
	 */
	@RequestMapping(value = "/insert")
	@Menu(type = "apps" , subtype = "batch" , access = true)
	@ApiOperation("批量插入批次数据")
    public ResponseEntity<RestResult> insert(HttpServletRequest request , @RequestBody RequestValues<Map<String, String>> values) {
    	if(values != null && values.getList()!=null && values.getList().size() > 0 && values.getList().size()<1000){
    		if(values!=null && !StringUtils.isBlank(values.getBatid())) {
    			JobDetail batch = batchRes.findByIdAndOrgi(values.getBatid(), values.getOrgi()) ;
    			String tableName =  "uk_"+UKTools.genIDByKey(values.getBatid()) ;
    	    	MetadataTable table = metadataRes.findByTablenameIgnoreCase(tableName) ;
    	    	
    	    	DSDataEvent event = new DSDataEvent();
    	    	
    	    	event.setTablename(tableName);
    	    	event.setDSData(new DSData(null ,null , null , super.getUser(request)));
    	    	event.setOrgi(super.getOrgi(request));
    	    	event.getValues().put("creater", super.getUser(request).getId()) ;
    	    	
    	    	if(batch!=null && table!=null && batch.isMapping()){
    	    		event.getDSData().setTask(table);
    		    	event.getDSData().setProcess(new BatchDataProcess(table, esDataExchange));
    		    	event.setOrgi(super.getOrgi(request));
    		    	event.setBatid(batch.getId());
    		    	event.getDSData().getReport().setOrgi(batch.getOrgi());
    		    	event.getDSData().getReport().setDataid(batch.getId());
    		    	event.getDSData().getReport().setOrgan(super.getUser(request).getOrgan());
    		    	event.getDSData().getReport().setTitle(batch.getName() + "_" + UKTools.dateFormate.format(new Date()));
    		    	event.getDSData().setJobDetail(batch);
    		    	reporterRes.save(event.getDSData().getReport()) ;
    		    	try {
						processData(request, event , table, values.getList(), values.getOrgi());
					} catch (Exception e) {
						e.printStackTrace();
					}
    	    	} 
    		}
    	}
        return new ResponseEntity<>(new RestResult(RestResultType.OK), HttpStatus.OK);
    }
	
	private void processData(HttpServletRequest request , DSDataEvent event ,MetadataTable table , List<Map<String,String>> data , String orgi) throws Exception{
		for(Map<String, String> value : data) {
			Map<Object, Object> values = new HashMap<Object , Object>() ;
			Map<Object, List<Object>> refValues = new HashMap<Object , List<Object>>() ;
			ArrayListMultimap<String, Object> multiValues = ArrayListMultimap.create();
			boolean skipDataVal = false; //跳过数据校验
			StringBuffer pkStr = new StringBuffer() , allStr = new StringBuffer();
			Iterator<String> iterator = value.keySet().iterator() ;
			while(iterator.hasNext()){
				String titleValue = iterator.next() ;
				if(!StringUtils.isBlank(titleValue)) {
					titleValue = titleValue.trim() ;
				}
				TableProperties tableProperties = getTableProperties(event, titleValue);
				if(tableProperties!=null && value!=null){
					String valuestr = value.get(titleValue) ;
					
					if(!StringUtils.isBlank(valuestr)) {
						
						if(tableProperties.isSreplace() && !StringUtils.isBlank(tableProperties.getCurstr())) {
							valuestr = valuestr.replaceAll(tableProperties.getCurstr(), !StringUtils.isBlank(tableProperties.getTarstr()) ? tableProperties.getTarstr() : "") ;
						}
						if(tableProperties.isModits()){
							if(!StringUtils.isBlank(valuestr)) {
								multiValues.put(tableProperties.getFieldname().toLowerCase(), valuestr) ;
							}
						}else{
							if(tableProperties.isPrivatefield() && !tableProperties.isSysfield()){
								values.put("pri_"+tableProperties.getFieldname().toLowerCase(), valuestr) ;
								valuestr = UKTools.md5(valuestr);
							}
							if(tableProperties.isSeldata()){
								//启用字典项字段，特殊处理
								SysDicRepository sysDicRes =  UKDataContext.getContext().getBean(SysDicRepository.class);
								if(!StringUtils.isBlank(tableProperties.getSeldatacode())){
									SysDic sysDic = sysDicRes.findByCode(tableProperties.getSeldatacode());
									if(sysDic != null){
										List<SysDic> resultList = sysDicRes.findByDicidAndNameLike(sysDic.getId(), valuestr);
										if(!resultList.isEmpty()){
											values.put(tableProperties.getFieldname().toLowerCase(), resultList.get(0).getId()) ;
										}else{
											values.put(tableProperties.getFieldname().toLowerCase(), valuestr) ;
										}
									}else{
										values.put(tableProperties.getFieldname().toLowerCase(), valuestr) ;
									}
								}else{
									values.put(tableProperties.getFieldname().toLowerCase(), valuestr) ;
								}
							}else if(tableProperties.isReffk() && refValues.get(tableProperties.getFieldname().toLowerCase())!=null){
								List<Object> keys = refValues.get(tableProperties.getFieldname().toLowerCase()) ;
								if(keys != null) {
									values.put(tableProperties.getFieldname().toLowerCase() , getRefid(tableProperties,refValues.get(tableProperties.getFieldname().toLowerCase()) , valuestr)) ;
								}
							}else{
								values.put(tableProperties.getFieldname().toLowerCase(), valuestr) ;
							}
							if(tableProperties.isPk() && !tableProperties.getFieldname().toLowerCase().equalsIgnoreCase("id")){
								pkStr.append(valuestr) ;
							}
						}
						allStr.append(valuestr) ;
					}
					event.getDSData().getReport().setBytes(event.getDSData().getReport().getBytes() + valuestr.length());
					event.getDSData().getReport().getAtompages().incrementAndGet() ;
				}
			}
			values.put("orgi", event.getOrgi()) ;
			if(values.get("id") == null){
				if(pkStr.length() > 0) {
					values.put("id", UKTools.md5(pkStr.append(event.getDSData().getTask().getTablename()).toString())) ;
				}else {
					values.put("id", UKTools.md5(allStr.append(event.getDSData().getTask().getTablename()).toString())) ;
				}
			}
			if(event.getValues()!=null && event.getValues().size() > 0){
				values.putAll(event.getValues());
			}
			values.putAll(multiValues.asMap());
			String validFaildMessage = null ;
			for(TableProperties tp : table.getTableproperty()){
				if(!StringUtils.isBlank(tp.getDefaultvaluetitle())) {
					String valuestr = (String) values.get(tp.getFieldname().toLowerCase()) ;
					if(tp.getDefaultvaluetitle().indexOf("required") >= 0 && StringUtils.isBlank(valuestr)) {
						skipDataVal = true ; validFaildMessage = "required" ;break ;
					}else if(valuestr!=null && (tp.getDefaultvaluetitle().indexOf("numstr") >= 0 && !valuestr.matches("[\\d]{1,}"))) {
						skipDataVal = true ; validFaildMessage = "numstr" ;break ;
					}else if(valuestr!=null && (tp.getDefaultvaluetitle().indexOf("datenum") >= 0 || tp.getDefaultvaluetitle().indexOf("datetime") >= 0 )) {
						if(!valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-[\\d]{2,2}") && !valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-[\\d]{2} [\\d]{2,2}:[\\d]{2,2}:[\\d]{2,2}")) {
							skipDataVal = true ; validFaildMessage = "datenum" ; break ;
						}else {
							if(valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-{1,1}")) {
								if("date".equals(tp.getDefaultfieldvalue())) {
									values.put(tp.getFieldname().toLowerCase(),UKTools.simpleDateFormat.parse(valuestr));
								}else {
									values.put(tp.getFieldname().toLowerCase(),UKTools.simpleDateFormat.format(UKTools.simpleDateFormat.parse(valuestr)));
								}
							}else if(valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-[\\d]{2,2} [\\d]{2,2}:[\\d]{2,2}:[\\d]{2,2}")) {
								if("date".equals(tp.getDefaultfieldvalue())) {
									values.put(tp.getFieldname().toLowerCase(),UKTools.dateFormate.parse(valuestr));
								}else {
									values.put(tp.getFieldname().toLowerCase(),UKTools.simpleDateFormat.format(UKTools.dateFormate.parse(valuestr)));
								}
								
							}
						}
					}
				}
				//联系人-获得时间，导入时表格中有值则用表格中的，否则置为当前时间
				if("touchtime".equals(tp.getFieldname()) && !StringUtils.isBlank((String)values.get("touchtime"))){
					String valuestr = (String)values.get("touchtime");
					if(valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-[\\d]{2,2}")){
						values.put("touchtime",UKTools.dateFormate.format(UKTools.dateFormate.parse(valuestr)));
					}else if(valuestr.matches("[\\d]{4,4}-[\\d]{2,2}-[\\d]{2,2} [\\d]{2,2}:[\\d]{2,2}:[\\d]{2,2}")){
						values.put("touchtime",UKTools.dateFormate.format(UKTools.dateFormate.parse(valuestr)));
					}else{
						values.put("touchtime",UKTools.dateFormate.format(new Date()));
					}
				}else if("touchtime".equals(tp.getFieldname())){
					values.put("touchtime",UKTools.dateFormate.format(new Date()));
				}
            	if(tp.isReffk() && !StringUtils.isBlank(tp.getReftbid()) && refValues.get(tp.getFieldname().toLowerCase()) == null){
            		DataExchangeInterface exchange = (DataExchangeInterface) UKDataContext.getContext().getBean(tp.getReftbid()) ;
            		exchange.process(data, event.getOrgi());
            	}
            }
			
			if(!values.containsKey("orgi")) {
				skipDataVal = true ;
			}
			values.put("creater", event.getValues().get("creater")) ;
			if (!StringUtils.isBlank(event.getTablename()) && event.getTablename().equals(UKDataContext.EsTable.UK_CONTACTS.toString())) {
				if (values.get("itemid")!=null) {
					String id = UKTools.md5(pkStr.append(values.get("itemid")).append(event.getTablename()).toString());
					if (!StringUtils.isBlank(id)) {
						DataExchangeInterface exchange = (DataExchangeInterface) UKDataContext.getContext().getBean("contacts") ;
	            		Contacts contacts = (Contacts) exchange.getDataByIdAndOrgi(id, values.get("orgi").toString());
	            		if (contacts == null) {
	            			values.put("id", id) ;
						}else {
							if (contacts.isDatastatus()) {
								values.put("id", id) ;
							}else {
								continue;
							}
						}
					}
				}
			}
			if(data!=null){
				/**
				 * 导入的数据，只写入ES
				 */
				if(skipDataVal == true) {	//跳过
					values.put("status", "invalid") ;
					values.put("validresult", "invalid") ;
					values.put("validmessage", validFaildMessage!=null ? validFaildMessage : "") ;
				}else {
					values.put("validresult", "valid") ;
				}
				values.put("status", UKDataContext.NamesDisStatusType.NOT.toString()) ;
				values.put("batid", event.getBatid()) ;
				
				values.put("createtime", System.currentTimeMillis()) ;
				values.put("callstatus", UKDataContext.NameStatusTypeEnum.NOTCALL.toString()) ;
				values.put("execid", event.getDSData().getReport().getId()) ;
				
				if(values.get("cusid")==null) {
					values.put("cusid", values.get("id"))  ;
				}
				if (values.get("cusname") != null) {
					values.put("ctype", UKDataContext.ContactsItemType.CUSTOMER.toString()) ;
				}else {
					values.put("ctype", UKDataContext.ContactsItemType.CONTACTS.toString()) ;
				}
				event.getDSData().getProcess().process(values);
				event.getDSData().getProcess().end();
				/**
				 * 访客信息表
				 */
			}
			if(skipDataVal == true) {	//跳过
				continue ;
			}
		}
	}
	
	
	private TableProperties getTableProperties(DSDataEvent event , String title){
		TableProperties tableProperties = null ; 
		for(TableProperties tp : event.getDSData().getTask().getTableproperty()){
			if(tp.getName().equalsIgnoreCase(title) || tp.getFieldname().equalsIgnoreCase(title)){
				tableProperties = tp ; break ;
			}
		}
		return tableProperties;
	}
	
	private String getRefid(TableProperties tp , List<Object> dataList , String value) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
		String id = "" ;
		for(Object data : dataList){
			Object target = null ;
			if(PropertyUtils.isReadable(data, "name")){
				target = BeanUtils.getProperty(data, "name") ;
				if(target!=null && target.equals(value)){
					id = BeanUtils.getProperty(data, "id") ;
				}
			}
			if(PropertyUtils.isReadable(data, "tag")){
				target = BeanUtils.getProperty(data, "tag") ;
				if(target!=null && target.equals(value)){
					id = BeanUtils.getProperty(data, "id") ;
				}
			}
			if(StringUtils.isBlank(id) && PropertyUtils.isReadable(data, "title")){
				target = BeanUtils.getProperty(data, "title") ; 
				if(target!=null && target.equals(value)){
					id = BeanUtils.getProperty(data, "id") ;
				}
			}
			if(StringUtils.isBlank(id)){
				target = BeanUtils.getProperty(data, "id") ; 
				if(target!=null && target.equals(value)){
					id = target.toString() ;
				}
			}
		}
		return id ;
	}
}